package com.yyw.foodie.utils;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

/**
 * @author 易煜玮
 * @ClassName FileUtils.java
 * @Description
 * @createTime 2021年06月02日 16:22:00
 */
@Component
public class FileUtils {


    /**
     * 文件存放的基础路径
     */
    @Value("${file.user-path}")
    private String basePathYaml;

    /**
     * 页面读取文件的前缀路径
     */
    @Value("${file.service-path}")
    private String serviceFilePath;

    private static String BASE_PATH = "";
    private static String SERVICE_PATH = "";

    @PostConstruct
    public void getBasePath() {
        // 静态方法无法直接获取非静态变量，只能初始化方式获取
        BASE_PATH = basePathYaml;
        SERVICE_PATH = serviceFilePath;
    }

    /**
     * 用户相关的文件存储文件夹
     */
    public static final String USER_FILE_PATH = "userFiles";

    /**
     * 用户头像上传
     * 首先调用通用的上传方法，通过传入的自定义路径，会自动拼成 base基础路径/自定义路径/自定义文件名前缀_文件名.后缀
     * 保存完毕后，因为我们在WebConfig.java 中配置了资源文件路径的映射，会自动去匹配基础路径下面所有的文件
     * 所以我们只返回了除了基础路径的子目录，即 /自定义路径/自定义文件名前缀_文件名.后缀
     * 再将这个文件 加上 服务器访问的路径，即 http://localhost:8088/自定义路径/自定义文件名前缀_文件名.后缀
     * 只有访问这个路径，才能直接在浏览器访问该文件，最终将这个路径保存在DB
     *
     * @param multipartFile 头像文件
     * @param useFileNamePrefix 文件名的前缀
     * @return  保存后的文件的相对路径
     */
    public static String uploadUserFace(MultipartFile multipartFile, String useFileNamePrefix) {
        String filePath = upload(multipartFile, USER_FILE_PATH + File.separator + useFileNamePrefix, useFileNamePrefix);
        // 为了防止页面有缓存，这里给图片地址拼接上时间，这样刷新页面才能重新获取头像，而不用用户强制刷新或者清楚缓存
        filePath += ("?t=" + DateUtil.getCurrentDateString(DateUtil.DATE_PATTERN));
        return SERVICE_PATH + filePath;
    }

    /**
     * 保存文件 并返回 相对路径的文件名
     *
     * @param multipartFile file
     * @param prefixPath    基于base路径的前置路径  basePath/xxx/
     * @param useFileNamePrefix   存储时指定 文件名的前缀
     * @return 文件存储的相对路径地址
     */
    public static String upload(MultipartFile multipartFile, String prefixPath, String useFileNamePrefix) {
        OutputStream out = null;
        String newFilePath = "";
        try {
            // 获取文件名称
            String filename = multipartFile.getOriginalFilename();
            String[] temps = filename.split("\\.");
            if (temps.length <= 1) {
                throw new IOException("文件名异常");
            }
            // 获取文件名后缀
            String suffix = temps[temps.length - 1];
            if (!suffix.equalsIgnoreCase("png") &&
                    !suffix.equalsIgnoreCase("jpg") &&
                    !suffix.equalsIgnoreCase("jpeg")) {
                throw new RuntimeException("图片格式不正确！");
            }
            // 拼接新的文件名
            if (StringUtils.isNoneBlank(useFileNamePrefix)) {
                filename = useFileNamePrefix + "_" + DateUtil.getCurrentDateString(DateUtil.DATE_PATTERN) + "." + suffix;
            }else {
                filename = DateUtil.getCurrentDateString(DateUtil.DATE_PATTERN) + "." + suffix;
            }
            String filePath = BASE_PATH + File.separator + prefixPath + File.separator + filename;
            // 修正分隔符
            filePath = repairPath(filePath);
            File saveFile = new File(filePath);
            if (saveFile.getParentFile() != null) {
                // 创建文件夹,递归创建
                saveFile.getParentFile().mkdirs();
            }
            out = new FileOutputStream(saveFile);
            // 保存图片
            IOUtils.copy(multipartFile.getInputStream(), out);
            // 返回相对路径名，不包括base的路径
            newFilePath = File.separator + prefixPath + File.separator + filename;
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        } finally {
            if (out != null) {
                try {
                    out.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return newFilePath;
    }


    /**
     * 修正路径，将 \\ 或 / 等替换为 File.separator
     *
     * @param path 待修正的路径
     * @return 修正后的路径
     */
    public static String repairPath(String path) {
        String p = StringUtils.replace(path, "\\", "/");
        p = StringUtils.join(StringUtils.split(p, "/"), "/");
        if (!StringUtils.startsWithAny(p, "/") && StringUtils.startsWithAny(path, "\\", "/")) {
            p += "/";
        }
        if (!StringUtils.endsWithAny(p, "/") && StringUtils.endsWithAny(path, "\\", "/")) {
            p = p + "/";
        }
        if (path != null && path.startsWith("/")) {
            // linux下路径
            p = "/" + p;
        }
        return p;
    }
}
